// Copyright (C) 1953-2022 NUDT
// Verilog module name - responder_response_generate
// Version: V4.1.0.20221206
// Created:
//         by - fenglin
////////////////////////////////////////////////////////////////////////////
// Description:
//         
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module responder_response_generate 
#(
parameter local_module_id = 12'd0
)
(
    i_clk  ,
    i_rst_n,
	
	iv_hcp_mid                            ,
    
    iv_data                               ,
	i_data_wr                             ,
	iv_port_id                            ,
	
	o_data_ready                          ,	

	ov_data                               ,
	o_data_wr                             ,
	ov_ptp_messagetype                    ,
	ov_port_id                            ,
    o_first_byte_valid                    ,
	
	iv_t2_p0                              ,	
	iv_t2_p1                              ,
	iv_t2_p2                              ,
	iv_t2_p3                              ,
	iv_t2_p4                              ,
	iv_t2_p5                              ,
	iv_t2_p6                              ,
	iv_t2_p7                              ,
	iv_t2_p8                              ,
	iv_t2_p9                              ,
	iv_t2_p10                              ,
	iv_t2_p11                              ,
	iv_t2_p12                              ,
	iv_t2_p13                              ,
	iv_t2_p14                              ,
	iv_t2_p15                              ,
	iv_t2_p16                              ,
	iv_t2_p17                              ,
	iv_t2_p18                              ,
	iv_t2_p19                              ,
	iv_t2_p20                              ,
	iv_t2_p21                              ,
	iv_t2_p22                              ,
	iv_t2_p23                              ,
	iv_t2_p24                              ,
	iv_t2_p25                              ,
	iv_t2_p26                              ,
	iv_t2_p27                              ,
	iv_t2_p28                              ,
	iv_t2_p29                              ,
	iv_t2_p30                              ,
    iv_t2_p31                              ,
	
	iv_t3                                  ,
	i_t3_wr                           
);

// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n; 
// pkt input                      ;
input      [11:0]       iv_hcp_mid     ;

input	   [8:0]	    iv_data        ;
input	         	    i_data_wr      ;
input	   [7:0]    	iv_port_id     ;

output reg              o_data_ready   ;
// pkt output to NMA
output reg [8:0]	    ov_data        ;
output reg	            o_data_wr      ;
output reg [3:0]        ov_ptp_messagetype     ;
output reg [7:0]        ov_port_id             ;
output reg              o_first_byte_valid     ;
//
input      [95:0]	    iv_t2_p0            ;
input      [95:0]	    iv_t2_p1            ;
input      [95:0]	    iv_t2_p2            ;
input      [95:0]	    iv_t2_p3            ;
input      [95:0]	    iv_t2_p4            ;
input      [95:0]	    iv_t2_p5            ;
input      [95:0]	    iv_t2_p6            ;      
input      [95:0]	    iv_t2_p7            ;
input      [95:0]	    iv_t2_p8            ;
input      [95:0]	    iv_t2_p9            ;
input      [95:0]	    iv_t2_p10           ;
input      [95:0]	    iv_t2_p11           ;
input      [95:0]	    iv_t2_p12           ;
input      [95:0]	    iv_t2_p13           ;
input      [95:0]	    iv_t2_p14           ;
input      [95:0]	    iv_t2_p15           ;
input      [95:0]	    iv_t2_p16           ;
input      [95:0]	    iv_t2_p17           ;
input      [95:0]	    iv_t2_p18           ;
input      [95:0]	    iv_t2_p19           ;
input      [95:0]	    iv_t2_p20           ;
input      [95:0]	    iv_t2_p21           ;
input      [95:0]	    iv_t2_p22           ;
input      [95:0]	    iv_t2_p23           ;
input      [95:0]	    iv_t2_p24           ;
input      [95:0]	    iv_t2_p25           ;
input      [95:0]	    iv_t2_p26           ;
input      [95:0]	    iv_t2_p27           ;
input      [95:0]	    iv_t2_p28           ;
input      [95:0]	    iv_t2_p29           ;
input      [95:0]	    iv_t2_p30           ;
input      [95:0]	    iv_t2_p31           ;

input      [95:0]       iv_t3               ;
input                   i_t3_wr             ;                  
//***************************************************
//               packet process
//***************************************************
reg       [15:0]              rv_req_sequence        ;
reg       [79:0]              rv_req_sourceportidentity;
reg       [3:0]               rv_req_majorSdoId      ;
reg       [95:0]              rv_t2                  ;
reg       [7:0]               rv_inport_id           ;
reg       [7:0]               rv_byte_cnt            ;
reg       [2:0]               rv_ipp_state           ;
localparam      IDLE_S                     = 3'd0,
                RECEIVE_REQ_S              = 3'd1,
                GENERATE_RESP_S            = 3'd2,
                WAIT_RESP_OUTPUT_S         = 3'd3,
				GENERATE_RESP_FOLLOW_UP_S  = 3'd4;
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n)begin
        rv_req_sequence           <= 16'b0;
        rv_req_sourceportidentity <= 80'b0;		
		rv_byte_cnt               <= 8'b0 ;
		rv_inport_id              <= 8'b0 ;
		
		ov_data            <= 9'b0;
        o_data_wr          <= 1'b0;
		ov_ptp_messagetype <= 4'b0;
		ov_port_id         <= 8'b0;
        o_first_byte_valid <= 1'b0;
		
		o_data_ready       <= 1'b1;

        rv_ipp_state       <= IDLE_S;        
    end
    else begin
        case(rv_ipp_state)
            IDLE_S:begin
                rv_req_sequence           <= 16'b0;
                rv_req_sourceportidentity <= 80'b0;					
				
				ov_port_id          <= 8'b0 ;
                o_first_byte_valid  <= 1'b0;
				ov_ptp_messagetype  <= 4'b0;
				ov_data             <= 9'b0;
				o_data_wr           <= 1'b0;			
				if(i_data_wr)begin//
                    rv_inport_id        <= iv_port_id ;
					o_data_ready        <= 1'b0;
					rv_byte_cnt         <= 8'd1 ;
					rv_ipp_state        <= RECEIVE_REQ_S;  
				end
				else begin
				    rv_inport_id    <= 8'b0 ;
				    o_data_ready    <= 1'b1 ;
					rv_byte_cnt     <= 8'b0 ;
					rv_ipp_state    <= IDLE_S;  
				end                    
            end
			RECEIVE_REQ_S:begin
                if(i_data_wr)begin
					rv_byte_cnt     <= rv_byte_cnt + 1'b1 ;
					rv_ipp_state    <= RECEIVE_REQ_S;  
                end
                else begin
                    rv_byte_cnt     <= 8'b0 ;
					rv_ipp_state    <= GENERATE_RESP_S; 
					case(rv_inport_id[4:0])
					    5'd0: rv_t2 <= iv_t2_p0;
						5'd1: rv_t2 <= iv_t2_p1;
						5'd2: rv_t2 <= iv_t2_p2;
						5'd3: rv_t2 <= iv_t2_p3;
						5'd4: rv_t2 <= iv_t2_p4;
						5'd5: rv_t2 <= iv_t2_p5;
						5'd6: rv_t2 <= iv_t2_p6;
						5'd7: rv_t2 <= iv_t2_p7;
						5'd8: rv_t2 <= iv_t2_p8;
						5'd9: rv_t2 <= iv_t2_p9;
						5'd10:rv_t2 <= iv_t2_p10;
						5'd11:rv_t2 <= iv_t2_p11;
						5'd12:rv_t2 <= iv_t2_p12;
						5'd13:rv_t2 <= iv_t2_p13;
						5'd14:rv_t2 <= iv_t2_p14;
						5'd15:rv_t2 <= iv_t2_p15;
						5'd16:rv_t2 <= iv_t2_p16;
						5'd17:rv_t2 <= iv_t2_p17;
						5'd18:rv_t2 <= iv_t2_p18;
						5'd19:rv_t2 <= iv_t2_p19;
						5'd20:rv_t2 <= iv_t2_p20;
						5'd21:rv_t2 <= iv_t2_p21;
						5'd22:rv_t2 <= iv_t2_p22;
						5'd23:rv_t2 <= iv_t2_p23;
						5'd24:rv_t2 <= iv_t2_p24;
						5'd25:rv_t2 <= iv_t2_p25;
						5'd26:rv_t2 <= iv_t2_p26;
						5'd27:rv_t2 <= iv_t2_p27;
						5'd28:rv_t2 <= iv_t2_p28;
						5'd29:rv_t2 <= iv_t2_p29;
						5'd30:rv_t2 <= iv_t2_p30;
						5'd31:rv_t2 <= iv_t2_p31;
						default:rv_t2 <= rv_t2;
					endcase
                end				
			    
				if(rv_byte_cnt == 8'd14)begin
                    rv_req_majorSdoId <= iv_data[7:4];
                end
				else begin
                    rv_req_majorSdoId <= rv_req_majorSdoId;
                end
                if((rv_byte_cnt >= 8'd34) && (rv_byte_cnt <= 8'd43))begin
                    rv_req_sourceportidentity <= {rv_req_sourceportidentity[71:0],iv_data[7:0]};
                end
                else begin
                    rv_req_sourceportidentity <= rv_req_sourceportidentity;
                end	

                if((rv_byte_cnt >= 8'd44) && (rv_byte_cnt <= 8'd45))begin
                    rv_req_sequence <= {rv_req_sequence[7:0],iv_data[7:0]};
                end
                else begin
                    rv_req_sequence <= rv_req_sequence;
                end					
			end
            GENERATE_RESP_S:begin	           
                rv_byte_cnt     <= rv_byte_cnt + 1'b1;
				ov_port_id      <= rv_inport_id      ;
				ov_ptp_messagetype <= 4'd3;
				o_data_wr       <= 1'b1;
				case(rv_byte_cnt)
				    //dmac
				    8'd0:begin
                        ov_data            <= {1'b1,8'h01};
                        o_first_byte_valid <= 1'b1;
                    end
                    8'd1:begin
                        ov_data            <= {1'b0,8'h80};
                        o_first_byte_valid <= 1'b0;
                    end
					8'd2:ov_data          <= {1'b0,8'hC2};
					8'd3:ov_data          <= {1'b0,8'h00};
					8'd4:ov_data          <= {1'b0,8'h00};
					8'd5:ov_data          <= {1'b0,8'h0E};
					//smac                
					8'd6:ov_data          <= {1'b0, 8'h66                                 };
					8'd7:ov_data          <= {1'b0, 8'h26                                 };
					8'd8:ov_data          <= {1'b0, 8'h62                                 };
					8'd9:ov_data          <= {1'b0, iv_hcp_mid[11:4]                      };
					8'd10:ov_data         <= {1'b0, iv_hcp_mid[3:0 ],local_module_id[11:8]};
					8'd11:ov_data         <= {1'b0, local_module_id[7:0  ]                };
					//eth type
					8'd12:ov_data         <= {1'b0,8'h88};
					8'd13:ov_data         <= {1'b0,8'hF7};
					//majorSdoId,messageType
					8'd14:ov_data         <= {1'b0,rv_req_majorSdoId,4'h3};
					//minorVersionPTP,versionPTP
					8'd15:ov_data         <= {1'b0,4'h0,4'h2};
					//messageLength
					8'd16:ov_data         <= {1'b0,8'h00};
					8'd17:ov_data         <= {1'b0,8'd54};
					//domainNumber
					8'd18:ov_data         <= {1'b0,8'h00};
					//minorSdoId
					8'd19:ov_data         <= {1'b0,8'h00};
					//Flags
					8'd20:ov_data         <= {1'b0,8'h02};
					8'd21:ov_data         <= {1'b0,8'h08};
					//correctionField
					8'd22:ov_data         <= {1'b0,8'h00};
					8'd23:ov_data         <= {1'b0,8'h00};
					8'd24:ov_data         <= {1'b0,8'h00};
					8'd25:ov_data         <= {1'b0,8'h00};
					8'd26:ov_data         <= {1'b0,8'h00};
					8'd27:ov_data         <= {1'b0,8'h00};
					8'd28:ov_data         <= {1'b0,8'h00};
					8'd29:ov_data         <= {1'b0,8'h00};
					//messageTypeSpecific
					8'd30:ov_data         <= {1'b0,8'h00};
					8'd31:ov_data         <= {1'b0,8'h00};
					8'd32:ov_data         <= {1'b0,8'h00};
					8'd33:ov_data         <= {1'b0,8'h00};
					//SourcePortIdentity
                    8'd34:ov_data         <= {1'b0,8'h66};
					8'd35:ov_data         <= {1'b0,8'h26};
					8'd36:ov_data         <= {1'b0,8'h62};
					8'd37:ov_data         <= {1'b0,8'hFF};
					8'd38:ov_data         <= {1'b0,8'hFE};
					8'd39:ov_data         <= {1'b0,iv_hcp_mid[11:4]                      };
					8'd40:ov_data         <= {1'b0,iv_hcp_mid[3:0 ],local_module_id[11:8]};
					8'd41:ov_data         <= {1'b0,local_module_id[7:0  ]                };
					8'd42:ov_data         <= {1'b0,8'h00};
					8'd43:ov_data         <= {1'b0,rv_inport_id};
					//sequenceId
                    8'd44:ov_data         <= {1'b0,rv_req_sequence[15:8]};
					8'd45:ov_data         <= {1'b0,rv_req_sequence[7:0] };
                    //controlField
					8'd46:ov_data         <= {1'b0,8'h05};
					//logMessageInterval
					8'd47:ov_data         <= {1'b0,8'd127};           
					//reserved                                        
					8'd48:ov_data         <= {1'b0,rv_t2[95:88]};     
					8'd49:ov_data         <= {1'b0,rv_t2[87:80]};     
					8'd50:ov_data         <= {1'b0,rv_t2[79:72]};     
					8'd51:ov_data         <= {1'b0,rv_t2[71:64]};     
					8'd52:ov_data         <= {1'b0,rv_t2[63:56]};     
					8'd53:ov_data         <= {1'b0,rv_t2[55:48]};     
					8'd54:ov_data         <= {1'b0,rv_t2[47:40]};     
					8'd55:ov_data         <= {1'b0,rv_t2[39:32]};     
					8'd56:ov_data         <= {1'b0,rv_t2[31:24]};     
					8'd57:ov_data         <= {1'b0,rv_t2[23:16]};     
					//reserved
					8'd58:ov_data         <= {1'b0,rv_req_sourceportidentity[79:72]};
					8'd59:ov_data         <= {1'b0,rv_req_sourceportidentity[71:64]};
					8'd60:ov_data         <= {1'b0,rv_req_sourceportidentity[63:56]};
					8'd61:ov_data         <= {1'b0,rv_req_sourceportidentity[55:48]};
					8'd62:ov_data         <= {1'b0,rv_req_sourceportidentity[47:40]};
					8'd63:ov_data         <= {1'b0,rv_req_sourceportidentity[39:32]};
					8'd64:ov_data         <= {1'b0,rv_req_sourceportidentity[31:24]};
					8'd65:ov_data         <= {1'b0,rv_req_sourceportidentity[23:16]};
					8'd66:ov_data         <= {1'b0,rv_req_sourceportidentity[15:8 ]};
					8'd67:begin                                             
					    ov_data         <= {1'b1,rv_req_sourceportidentity[7:0  ]};
						rv_ipp_state    <= WAIT_RESP_OUTPUT_S;
				    end  
                endcase
            end
			WAIT_RESP_OUTPUT_S:begin
				ov_data         <= 9'b0;
				o_data_wr       <= 1'b0;
				
				rv_byte_cnt     <= 8'b0;

				if(i_t3_wr)begin
                    rv_ipp_state    <= GENERATE_RESP_FOLLOW_UP_S;
                end
                else begin
                    rv_ipp_state    <= WAIT_RESP_OUTPUT_S;
                end				
			end	
            GENERATE_RESP_FOLLOW_UP_S:begin	           
                rv_byte_cnt     <= rv_byte_cnt + 1'b1;
				ov_port_id      <= rv_inport_id      ;
				ov_ptp_messagetype <= 4'ha;
				o_data_wr       <= 1'b1;
				case(rv_byte_cnt)
				    //dmac
				    8'd0:begin
                        ov_data            <= {1'b1,8'h01};
                        o_first_byte_valid <= 1'b1;
                    end
                    8'd1:begin
                        ov_data            <= {1'b0,8'h80};
                        o_first_byte_valid <= 1'b0;
                    end
					8'd2:ov_data          <= {1'b0,8'hC2};
					8'd3:ov_data          <= {1'b0,8'h00};
					8'd4:ov_data          <= {1'b0,8'h00};
					8'd5:ov_data          <= {1'b0,8'h0E};
					//smac                
					8'd6:ov_data          <= {1'b0, 8'h66                                 };
					8'd7:ov_data          <= {1'b0, 8'h26                                 };
					8'd8:ov_data          <= {1'b0, 8'h62                                 };
					8'd9:ov_data          <= {1'b0, iv_hcp_mid[11:4]                      };
					8'd10:ov_data         <= {1'b0, iv_hcp_mid[3:0 ],local_module_id[11:8]};
					8'd11:ov_data         <= {1'b0, local_module_id[7:0  ]                };
					//eth type
					8'd12:ov_data         <= {1'b0,8'h88};
					8'd13:ov_data         <= {1'b0,8'hF7};
					//majorSdoId,messageType
					8'd14:ov_data         <= {1'b0,rv_req_majorSdoId,4'hA};
					//minorVersionPTP,versionPTP
					8'd15:ov_data         <= {1'b0,4'h0,4'h2};
					//messageLength
					8'd16:ov_data         <= {1'b0,8'h00};
					8'd17:ov_data         <= {1'b0,8'd54};
					//domainNumber
					8'd18:ov_data         <= {1'b0,8'h00};
					//minorSdoId
					8'd19:ov_data         <= {1'b0,8'h00};
					//Flags
					8'd20:ov_data         <= {1'b0,8'h00};
					8'd21:ov_data         <= {1'b0,8'h08};
					//correctionField
					8'd22:ov_data         <= {1'b0,8'h00};
					8'd23:ov_data         <= {1'b0,8'h00};
					8'd24:ov_data         <= {1'b0,8'h00};
					8'd25:ov_data         <= {1'b0,8'h00};
					8'd26:ov_data         <= {1'b0,8'h00};
					8'd27:ov_data         <= {1'b0,8'h00};
					8'd28:ov_data         <= {1'b0,8'h00};
					8'd29:ov_data         <= {1'b0,8'h00};
					//messageTypeSpecific
					8'd30:ov_data         <= {1'b0,8'h00};
					8'd31:ov_data         <= {1'b0,8'h00};
					8'd32:ov_data         <= {1'b0,8'h00};
					8'd33:ov_data         <= {1'b0,8'h00};
					//SourcePortIdentity
                    8'd34:ov_data         <= {1'b0,8'h66};
					8'd35:ov_data         <= {1'b0,8'h26};
					8'd36:ov_data         <= {1'b0,8'h62};
					8'd37:ov_data         <= {1'b0,8'hFF};
					8'd38:ov_data         <= {1'b0,8'hFE};
					8'd39:ov_data         <= {1'b0,iv_hcp_mid[11:4]                      };
					8'd40:ov_data         <= {1'b0,iv_hcp_mid[3:0 ],local_module_id[11:8]};
					8'd41:ov_data         <= {1'b0,local_module_id[7:0  ]                };
					8'd42:ov_data         <= {1'b0,8'h00};
					8'd43:ov_data         <= {1'b0,rv_inport_id};
					//sequenceId
                    8'd44:ov_data         <= {1'b0,rv_req_sequence[15:8]};
					8'd45:ov_data         <= {1'b0,rv_req_sequence[7:0] };
                    //controlField
					8'd46:ov_data         <= {1'b0,8'h05};
					//logMessageInterval
					8'd47:ov_data         <= {1'b0,8'd127};
					//reserved
					8'd48:ov_data         <= {1'b0,iv_t3[95:88]};
					8'd49:ov_data         <= {1'b0,iv_t3[87:80]};
					8'd50:ov_data         <= {1'b0,iv_t3[79:72]};
					8'd51:ov_data         <= {1'b0,iv_t3[71:64]};
					8'd52:ov_data         <= {1'b0,iv_t3[63:56]};
					8'd53:ov_data         <= {1'b0,iv_t3[55:48]};
					8'd54:ov_data         <= {1'b0,iv_t3[47:40]};
					8'd55:ov_data         <= {1'b0,iv_t3[39:32]};
					8'd56:ov_data         <= {1'b0,iv_t3[31:24]};
					8'd57:ov_data         <= {1'b0,iv_t3[23:16]};
					//reserved
					8'd58:ov_data         <= {1'b0,rv_req_sourceportidentity[79:72]};
					8'd59:ov_data         <= {1'b0,rv_req_sourceportidentity[71:64]};
					8'd60:ov_data         <= {1'b0,rv_req_sourceportidentity[63:56]};
					8'd61:ov_data         <= {1'b0,rv_req_sourceportidentity[55:48]};
					8'd62:ov_data         <= {1'b0,rv_req_sourceportidentity[47:40]};
					8'd63:ov_data         <= {1'b0,rv_req_sourceportidentity[39:32]};
					8'd64:ov_data         <= {1'b0,rv_req_sourceportidentity[31:24]};
					8'd65:ov_data         <= {1'b0,rv_req_sourceportidentity[23:16]};
					8'd66:ov_data         <= {1'b0,rv_req_sourceportidentity[15:8 ]};
					8'd67:begin                                             
					    ov_data         <= {1'b1,rv_req_sourceportidentity[7:0  ]};
						rv_ipp_state    <= IDLE_S;
				    end  
                endcase
            end			          
            default:begin
                ov_data            <= 9'b0;
				o_data_wr          <= 1'b0;
                o_first_byte_valid <= 1'b0;
                o_data_ready       <= 1'b1;				
				rv_ipp_state       <= IDLE_S;  
            end
        endcase
    end
end
endmodule